package com.campus.secondhand.util;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.util.Date;

/**
 * JWT工具类：生成登录令牌（token）、验证令牌是否有效、从令牌中提取用户名
 */
@Component
public class JwtUtil {
    // 令牌过期时间（2小时，单位：毫秒）
    @Value("${jwt.expiration:7200000}")
    private long expiration;

    // 密钥（必须足够长，生产环境建议配置在环境变量，这里简化用固定密钥）
    private final String secret = "campus-secondhand-platform-secret-key-123456";

    /**
     * 生成令牌（用户登录成功后调用）
     */
    public String generateToken(UserDetails userDetails) {
        SecretKey key = Keys.hmacShaKeyFor(secret.getBytes());
        return Jwts.builder()
                .setSubject(userDetails.getUsername())  // 把用户名存到令牌里
                .setIssuedAt(new Date())                // 令牌签发时间
                .setExpiration(new Date(System.currentTimeMillis() + expiration))  // 过期时间
                .signWith(key)                          // 用密钥签名（防止令牌被篡改）
                .compact();
    }

    /**
     * 验证令牌是否有效（比如用户访问需要登录的接口时）
     */
    public boolean validateToken(String token, UserDetails userDetails) {
        String username = extractUsername(token);
        // 验证：用户名一致 + 令牌没过期
        return username.equals(userDetails.getUsername()) && !isTokenExpired(token);
    }

    /**
     * 从令牌中提取用户名（比如根据令牌获取当前登录用户）
     */
    public String extractUsername(String token) {
        return extractClaims(token).getSubject();
    }

    /**
     * 提取令牌中的数据（比如用户名、过期时间）
     */
    private Claims extractClaims(String token) {
        SecretKey key = Keys.hmacShaKeyFor(secret.getBytes());
        return Jwts.parserBuilder()
                .setSigningKey(key)
                .build()
                .parseClaimsJws(token)
                .getBody();
    }

    /**
     * 检查令牌是否过期
     */
    private boolean isTokenExpired(String token) {
        return extractClaims(token).getExpiration().before(new Date());
    }
}
